package com.taylor.nio;

import org.testng.annotations.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * @Desc : NIO 还支持通过多个 Buffer（即 Buffer数组）完成读写操作，即 Scattering 和 Gathering
 *              使用 ServerSocketChannel 和 SocketChannel 网络
 * @Author ： taylor
 * @Date ：2021/6/26 18:38
 */
public class ScatteringAndGatheringTest {

    @Test
    public void test() {
        try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
             SocketChannel socketChannel = serverSocketChannel.accept()) {
            InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);
            //绑定端口到 socket，并启动
            serverSocketChannel.socket().bind(inetSocketAddress);
            //创建 buffer 数组
            ByteBuffer[] byteBuffers = new ByteBuffer[2];
            byteBuffers[0] = ByteBuffer.allocate(5);
            byteBuffers[1] = ByteBuffer.allocate(3);

            //假定从客户端接收 8 个字节
            int messageLength = 8;
            //循环的读取
            while (true) {
                int lenRead = 0;

                while (lenRead < messageLength) {
                    long l = socketChannel.read(byteBuffers);
                    //累计读取的字节数
                    lenRead += l;
                    System.out.println("lenRead = " + lenRead);
                    //使用流打印,看看当前的这个 buffer 的 position 和 limit
                    Arrays.asList(byteBuffers).stream()
                            .map(buffer -> "position = " + buffer.position() + ", limit = " + buffer.limit())
                            .forEach(System.out::println);
                }

                //将所有的 buffer 进行 flip
                Arrays.asList(byteBuffers).forEach(buffer -> buffer.flip());
                //将数据读出显示到客户端
                long lenWrite = 0;
                while (lenWrite < messageLength) {
                    long l = socketChannel.write(byteBuffers);
                    lenWrite += l;
                }

                //将所有的buffer进行clear
                Arrays.asList(byteBuffers).forEach(buffer -> buffer.clear());

                System.out.println("lenRead = " + lenRead + ", lenWrite = " + lenWrite + ", messageLength = " + messageLength);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
